home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / gui / bgui11b.lha / ARexxClass / ARexxClass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-26  |  36.3 KB  |  1,015 lines

  1. /*
  2. **         $RCSfile: arexxclass.c,v $
  3. **      Description: BOOPSI ARexx interface class.
  4. **        Copyright: (C) Copyright 1994 Jaba Development.
  5. **                   (C) Copyright 1994 Jan van den Baard.
  6. **                   All Rights Reserved.
  7. **
  8. **          $Author: jaba $
  9. **        $Revision: 1.2 $
  10. **            $Date: 1994/09/25 15:08:41 $
  11. **/
  12.  
  13. /*
  14. **      Uncomment the following line if you want the
  15. **      class to use memory pools and you have got
  16. **      the 3.1 amiga.lib. You need the 3.1 amiga.lib
  17. **      because the earlier version do not contain
  18. **      link versions of the pool routines.
  19. **/
  20.  
  21. /* #define POOLS */
  22.  
  23. /*
  24. **      When POOLS is defined the class will
  25. **      use the allocation routines as defined
  26. **      in the source. Otherwise it simply
  27. **      allocates memory from the system pool.
  28. **/
  29. #ifdef POOLS
  30. #define AllocMemory(s)          GetMem( ad, s )
  31. #define FreeMemory(p)           PutMem( ad, p )
  32. #else
  33. #define AllocMemory(s)          AllocVec( s, MEMF_PUBLIC | MEMF_CLEAR )
  34. #define FreeMemory(p)           FreeVec( p )
  35. #endif
  36.  
  37. /*
  38. **      Include necessary headers.
  39. **/
  40. #include "ARexxClass.h"
  41.  
  42. #include <proto/intuition.h>
  43. #include <proto/utility.h>
  44. #include <proto/rexxsyslib.h>
  45. #include <proto/exec.h>
  46. #include <proto/dos.h>
  47.  
  48. #include <clib/alib_protos.h>
  49.  
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include <ctype.h>
  53.  
  54. /*
  55. **      Compiler crap. Should compile under SAS this way...
  56. **/
  57. #ifdef _DCC
  58. #define SAVEDS __geta4
  59. #define ASM
  60. #define REG(x) __ ## x
  61. #else
  62. #define SAVEDS __saveds
  63. #define ASM __asm
  64. #define REG(x) register __ ## x
  65. #endif
  66.  
  67. /*
  68. **      Object instance data. Every object
  69. **      created from this class has this
  70. **      data.
  71. **/
  72. typedef struct {
  73.         struct MsgPort                  *ad_Port;       /* Host message port.         */
  74.         UBYTE                           *ad_HostName;   /* Host name.                 */
  75.         UBYTE                           *ad_FileExt;    /* File extention.            */
  76.         ULONG                            ad_PendCnt;    /* Messages still un-reply'd. */
  77.         REXXCOMMAND                     *ad_Commands;   /* Host command list.         */
  78.         struct RDArgs                   *ad_DOSParser;  /* ReadArgs() parser.         */
  79.         UWORD                            ad_Flags;      /* See below.                 */
  80. #ifdef POOLS
  81.         APTR                             ad_MemPool;    /* Memory pool.               */
  82. #endif
  83. } AD;
  84.  
  85. /*
  86. **      Static module prototypes of functions
  87. **      defined after they are referenced.
  88. **/
  89. STATIC ULONG SAVEDS ASM ARexxDispatch( REG(A0) Class *cl, REG(A2) Object *obj, REG(A1) Msg );
  90.  
  91. /*
  92. **      Class initialization. Simply creates the
  93. **      class and set's up the dispatcher.
  94. **/
  95. Class *InitARexxClass( void )
  96. {
  97.         Class                   *cl;
  98.  
  99.         if ( cl = MakeClass( NULL, ROOTCLASS, NULL, sizeof( AD ), 0L ))
  100.                 cl->cl_Dispatcher.h_Entry = (HOOKFUNC)ARexxDispatch;
  101.  
  102.         return( cl );
  103. }
  104.  
  105. /*
  106. **      Free the class. A simply FreeClass()
  107. **      would suffice but in the future this
  108. **      may do more.
  109. **/
  110. BOOL FreeARexxClass( Class *cl )
  111. {
  112.         return( FreeClass( cl ));
  113. }
  114.  
  115. /*
  116. **      These routines are only compiled when
  117. **      POOLS is defined. In that case the memory
  118. **      allocations are done in the object it's
  119. **      memory pool.
  120. **/
  121. #ifdef POOLS
  122. /*
  123. **      Pool allocation.
  124. **/
  125. STATIC APTR GetMem( AD *ad, ULONG size )
  126. {
  127.         ULONG                   *ptr;
  128.  
  129.         /*
  130.         **      Allocate the memory. Size is tracked so we do not
  131.         **      need to remember it when deallocating the memory again.
  132.         **/
  133.         if ( ptr = LibAllocPooled( ad->ad_MemPool, size + sizeof( ULONG ))) {
  134.                 /*
  135.                 **      Store allocation size.
  136.                 **/
  137.                 *ptr = size + sizeof( ULONG );
  138.                 /*
  139.                 **      Adjust pointer.
  140.                 **/
  141.                 ptr++;
  142.         }
  143.         return(( APTR )ptr );
  144. }
  145.  
  146. /*
  147. **      Pool freeing.
  148. **/
  149. STATIC VOID PutMem( AD *ad, APTR mem )
  150. {
  151.         ULONG                   *ptr = ( ULONG * )mem;
  152.  
  153.         /*
  154.         **      Retrieve the original allocation.
  155.         **/
  156.         ptr--;
  157.  
  158.         /*
  159.         **      Deallocate.
  160.         **/
  161.         LibFreePooled( ad->ad_MemPool, ptr, *ptr );
  162. }
  163. #endif
  164.  
  165. /*
  166. **      Duplicate a string.
  167. **/
  168. STATIC UBYTE *DupStr( AD *ad, UBYTE *str )
  169. {
  170.         UBYTE                   *dup = AllocMemory( strlen( str ) + 1 );
  171.  
  172.         /*
  173.         **      Allocation OK?
  174.         **/
  175.         if ( dup )
  176.                 /*
  177.                 **      Copy the string.
  178.                 **/
  179.                 strcpy( dup, str );
  180.  
  181.         return( dup );
  182. }
  183.  
  184. /*
  185. **      Reply a rexx command.
  186. **/
  187. STATIC VOID ReplyRexxCommand( struct RexxMsg *rxm, LONG prim, LONG sec, UBYTE *res )
  188. {
  189.         UBYTE           buf[ 16 ];
  190.  
  191.         /*
  192.         **      Result wanted?
  193.         **/
  194.         if ( rxm->rm_Action & RXFF_RESULT ) {
  195.                 /*
  196.                 **      Primary result?
  197.                 **/
  198.                 if ( ! prim ) {
  199.                         /*
  200.                         **      We setup the secondary result to
  201.                         **      the result string when one was passed.
  202.                         **/
  203.                         sec = res ? ( LONG )CreateArgstring( res, strlen( res )) : 0L;
  204.                 } else {
  205.                         /*
  206.                         **      Primary result bigger than 0?
  207.                         **/
  208.                         if ( prim > 0 ) {
  209.                                 /*
  210.                                 **      Setup the result field
  211.                                 **      to point to a string containing
  212.                                 **      the secondary result number.
  213.                                 **/
  214.                                 sprintf( buf, "%ld", sec );
  215.                                 res = buf;
  216.                         } else {
  217.                                 /*
  218.                                 **      Negate primary result and
  219.                                 **      setup the result field to
  220.                                 **      the secondary result.
  221.                                 **/
  222.                                 prim = -prim;
  223.                                 res = ( UBYTE * )sec;
  224.                         }
  225.  
  226.                         /*
  227.                         **      Setup ARexx it's "RC2" variable to
  228.                         **      the result.
  229.                         **/
  230.                         SetRexxVar(( struct Message * )rxm, "RC2", res, strlen( res ));
  231.  
  232.                         /*
  233.                         **      Clear secondary result.
  234.                         **/
  235.                         sec = 0L;
  236.                 }
  237.         } else if ( prim < 0 )
  238.                 /*
  239.                 **      Negate primary result.
  240.                 **/
  241.                 prim = -prim;
  242.  
  243.         /*
  244.         **      Setup result fields.
  245.         **/
  246.         rxm->rm_Result1 = prim;
  247.         rxm->rm_Result2 = sec;
  248.  
  249.         /*
  250.         **      Reply the RexxMsg.
  251.         **/
  252.         ReplyMsg(( struct Message * )rxm );
  253. }
  254.  
  255. /*
  256. **      Free a RexxMsg command.
  257. **/
  258. STATIC VOID FreeRexxCommand( struct RexxMsg *rxm )
  259. {
  260.         /*
  261.         **      Delete the result Argstring.
  262.         **/
  263.         if ( ! rxm->rm_Result1 && rxm->rm_Result2 )
  264.                 DeleteArgstring(( UBYTE * )rxm->rm_Result2 );
  265.  
  266.         /*
  267.         **      Close input handle.
  268.         **/
  269.         if ( rxm->rm_Stdin && rxm->rm_Stdin != Input()) {
  270.                 /*
  271.                 **      If the output handle is the
  272.                 **      same as the input handle we
  273.                 **      can safely clear it.
  274.                 **/
  275.                 if ( rxm->rm_Stdout == rxm->rm_Stdin )
  276.                         rxm->rm_Stdout = NULL;
  277.                 Close( rxm->rm_Stdin );
  278.                 rxm->rm_Stdin = NULL;
  279.         }
  280.  
  281.         /*
  282.         **      Close output handle if it is not
  283.         **      the same as Stdin.
  284.         **/
  285.         if ( rxm->rm_Stdout && rxm->rm_Stdout != Output()) {
  286.                 Close( rxm->rm_Stdout );
  287.                 rxm->rm_Stdout = NULL;
  288.         }
  289.  
  290.         /*
  291.         **      Delete the command Argstring.
  292.         **/
  293.         DeleteArgstring(( UBYTE * )ARG0( rxm ));
  294.         /*
  295.         **      Delete the message itself.
  296.         **/
  297.         DeleteRexxMsg( rxm );
  298. }
  299.  
  300. /*
  301. **      Create a RexxMsg command.
  302. **/
  303. STATIC struct RexxMsg *CreateRexxCommand( AD *ad, UBYTE *comname, BPTR handle )
  304. {
  305.         struct RexxMsg                  *rxm;
  306.  
  307.         /*
  308.         **      Create the RexxMsg.
  309.         **/
  310.         if ( rxm = CreateRexxMsg( ad->ad_Port, ad->ad_FileExt, ad->ad_HostName )) {
  311.                 /*
  312.                 **      Create the Argstring.
  313.                 **/
  314.                 if ( rxm->rm_Args[ 0 ] = CreateArgstring( comname, strlen( comname ))) {
  315.                         /*
  316.                         **      Setup action flags.
  317.                         **/
  318.                         rxm->rm_Action = RXCOMM | RXFF_RESULT;
  319.                         /*
  320.                         **      Setup file handles.
  321.                         **/
  322.                         rxm->rm_Stdin  = rxm->rm_Stdout = handle;
  323.                         return( rxm );
  324.                 }
  325.                 /*
  326.                 **      Argstring creation failed.
  327.                 **/
  328.                 DeleteRexxMsg( rxm );
  329.         }
  330.         return( NULL );
  331. }
  332.  
  333. /*
  334. **      Send a RexxMsg command to the
  335. **      ARexx server.
  336. **/
  337. STATIC struct RexxMsg *CommandToRexx( AD *ad, struct RexxMsg *rxm )
  338. {
  339.         struct MsgPort          *rxp;
  340.  
  341.         /*
  342.         **      Try to find the "REXX"
  343.         **      message port.
  344.         **/
  345.         Forbid();
  346.  
  347.         if ( ! ( rxp = FindPort( RXSDIR ))) {
  348.                 /*
  349.                 **      Oops. ARexx server
  350.                 **      not active.
  351.                 **/
  352.                 Permit();
  353.                 return( NULL );
  354.         }
  355.  
  356.         /*
  357.         **      Send off the message.
  358.         **/
  359.         PutMsg( rxp, &rxm->rm_Node );
  360.  
  361.         Permit();
  362.  
  363.         /*
  364.         **      Increase pending counter.
  365.         **/
  366.         ad->ad_PendCnt++;
  367.  
  368.         return( rxm );
  369. }
  370.  
  371. /*
  372. **      Send a command to the ARexx server.
  373. **/
  374. STATIC struct RexxMsg *SendRexxCommand( AD *ad, UBYTE *comname, BPTR handle )
  375. {
  376.         struct RexxMsg                  *rxm;
  377.  
  378.         /*
  379.         **      Create a RexxMsg command and
  380.         **      send it off to the ARexx server.
  381.         **/
  382.         if ( rxm = CreateRexxCommand( ad, comname, handle ))
  383.                 return( CommandToRexx( ad, rxm ));
  384.  
  385.         return( NULL );
  386. }
  387.  
  388. STATIC REXXCOMMAND *FindRXCommand( AD *ad, UBYTE *comname, UWORD len )
  389. {
  390.         REXXCOMMAND             *rc = ad->ad_Commands;
  391.  
  392.         while ( rc->rc_Func ) {
  393.                 if ( ! strnicmp( comname, rc->rc_Name, len ) && isspace( comname[ strlen( rc->rc_Name ) ] ))
  394.                         return( rc );
  395.                 rc++;
  396.         }
  397.  
  398.         return( NULL );
  399. }
  400.  
  401. /*
  402. **      Execute a command.
  403. **/
  404. STATIC VOID DoRXCommand( AD *ad, struct RexxMsg *rxm )
  405. {
  406.         struct RexxMsg                  *rm;
  407.         REXXCOMMAND                     *rco;
  408.         REXXARGS                        *ra;
  409.         UBYTE                           *comname, *args, *tmp, *result = NULL;
  410.         LONG                             rc = 20, rc2 = 0;
  411.         UWORD                            numargs = 0, len = 0;
  412.  
  413.         /*
  414.         **      Allocate memory for the command
  415.         **      name and it's argument string.
  416.         **/
  417.         if ( ! ( comname = ( UBYTE * )AllocMemory( strlen(( UBYTE * )ARG0( rxm )) + 2 ))) {
  418.                 rc2 = ERROR_NO_FREE_STORE;
  419.                 return;
  420.         }
  421.  
  422.         /*
  423.         **      Copy command name and argument string.
  424.         **/
  425.         strcpy( comname, ( UBYTE * )ARG0( rxm ));
  426.  
  427.         /*
  428.         **      ReadArgs() requires the argument
  429.         **      string to end with a newline.
  430.         **/
  431.         strcat( comname, "\n" );
  432.  
  433.         /*
  434.         **      Find the length of the command
  435.         **      the start of the arguments.
  436.         **/
  437.         args = comname;
  438.         while ( isspace( *args )) args++;
  439.         tmp  = args;
  440.         while ( ! isspace( *args )) { len++; args++; }
  441.  
  442.         /*
  443.         **      Find the command.
  444.         **/
  445.         if ( rco = FindRXCommand( ad, tmp, len )) {
  446.                 /*
  447.                 **      Allocate REXXARGS structure.
  448.                 **/
  449.                 if ( ra = ( REXXARGS * )AllocMemory( sizeof( REXXARGS ))) {
  450.                         /*
  451.                         **      Count number of expected args.
  452.                         **/
  453.                         if ( rco->rc_ArgTemplate ) {
  454.                                 tmp = rco->rc_ArgTemplate;
  455.                                 while ( *tmp != '\n' ) {
  456.                                         if ( *tmp++ == ',' ) numargs++;
  457.                                 }
  458.                                 numargs++;
  459.                                 /*
  460.                                 **      Allocate arg array.
  461.                                 **/
  462.                                 if ( ra->ra_ArgList = ( ULONG * )AllocMemory( numargs * sizeof( ULONG ))) {
  463.                                         /*
  464.                                         **      Setup RDArgs.
  465.                                         **/
  466.                                         ad->ad_DOSParser->RDA_Source.CS_Buffer = args;
  467.                                         ad->ad_DOSParser->RDA_Source.CS_Length = strlen( args );
  468.                                         ad->ad_DOSParser->RDA_Source.CS_CurChr = 0;
  469.                                         ad->ad_DOSParser->RDA_DAList           = NULL;
  470.                                         ad->ad_DOSParser->RDA_Buffer           = NULL;
  471.                                         /*
  472.                                         **      Parse args.
  473.                                         **/
  474.                                         if ( ReadArgs( rco->rc_ArgTemplate, ra->ra_ArgList, ad->ad_DOSParser )) {
  475.                                                 /*
  476.                                                 **      Call the REXX routine.
  477.                                                 **/
  478.                                                 ( rco->rc_Func )( ra, rxm );
  479.  
  480.                                                 rc     = ra->ra_RC;
  481.                                                 rc2    = ra->ra_RC2;
  482.                                                 result = ra->ra_Result;
  483.  
  484.                                                 FreeArgs( ad->ad_DOSParser );
  485.                                         } else {
  486.                                                 rc = 10;
  487.                                                 rc2 = IoErr();
  488.                                         }
  489.                                         FreeMemory( ra->ra_ArgList );
  490.                                 } else
  491.                                         rc2 = ERROR_NO_FREE_STORE;
  492.                         } else {
  493.                                 /*
  494.                                 **      No args.
  495.                                 **/
  496.                                 ( rco->rc_Func )( ra, rxm );
  497.  
  498.                                 rc     = ra->ra_RC;
  499.                                 rc2    = ra->ra_RC2;
  500.                                 result = ra->ra_Result;
  501.                         }
  502.                         FreeMemory( ra );
  503.                 } else
  504.                         rc2 = ERROR_NO_FREE_STORE;
  505.         } else {
  506.                 /*
  507.                 **      Not found in our list?
  508.                 **      Maybe it's a script.
  509.                 **/
  510.                 if ( rm = CreateRexxCommand( ad, ( UBYTE * )ARG0( rxm ), NULL )) {
  511.                         /*
  512.                         **      Save original message.
  513.                         **/
  514.                         rm->rm_Args[ 15 ] = ( STRPTR )rxm;
  515.                         /*
  516.                         **      Let the REXX server see what
  517.                         **      it can do with this.
  518.                         **/
  519.                         if ( ! CommandToRexx( ad, rm ))
  520.                                 rc2 = ERROR_NOT_IMPLEMENTED;
  521.                 } else
  522.                         rc2 = ERROR_NO_FREE_STORE;
  523.  
  524.                 goto byeBye;
  525.         }
  526.  
  527.         ReplyRexxCommand( rxm, rc, rc2, result );
  528.  
  529.         byeBye:
  530.  
  531.         FreeMemory( comname );
  532. }
  533.  
  534. /*
  535. **      OM_NEW.
  536. **/
  537. STATIC ULONG ARexxNew( Class *cl, Object *obj, struct opSet *ops )
  538. {
  539.         struct TagItem         *attr = ops->ops_AttrList, *tag;
  540.         struct MsgPort         *mp;
  541.         AD                     *ad;
  542.         ULONG                   rc, *ecode, ext = 1L;
  543.         UBYTE                   unique_name[ 80 ], *tmp;
  544.  
  545.         /*
  546.         **      Let the superclass set us up...
  547.         **/
  548.         if ( rc = ( ULONG )DoSuperMethodA( cl, obj, ( Msg )ops )) {
  549.                 /*
  550.                 **      Get the instance data.
  551.                 **/
  552.                 ad = ( AD * )INST_DATA( cl, rc );
  553.                 /*
  554.                 **      Safety precautions.
  555.                 **/
  556.                 bzero(( char * )ad, sizeof( AD ));
  557.  
  558.                 /*
  559.                 **      First see if we got error storage.
  560.                 **/
  561.                 if ( tag = FindTagItem( AC_ErrorCode, attr ))
  562.                         ecode = ( ULONG * )tag->ti_Data;
  563.  
  564. #ifdef POOLS
  565.                 /*
  566.                 **      Create a memory pool.
  567.                 **/
  568.                 if ( ad->ad_MemPool = LibCreatePool( MEMF_PUBLIC | MEMF_CLEAR, 4096L, 4096L )) {
  569. #endif
  570.                 /*
  571.                 **      Create port if a
  572.                 **      host name is supplied.
  573.                 **/
  574.                 if ( tag = FindTagItem( AC_HostName, attr )) {
  575.                         /*
  576.                         **      Store host name.
  577.                         **/
  578.                         ad->ad_HostName = ( UBYTE * )tag->ti_Data;
  579.                         /*
  580.                         **      Name valid?
  581.                         **/
  582.                         if ( ad->ad_HostName && *ad->ad_HostName ) {
  583.                                 /*
  584.                                 **      Make the name unique.
  585.                                 **/
  586.                                 sprintf( unique_name, "%s.1", ad->ad_HostName );
  587.                                 Forbid();
  588.                                 while (( mp = FindPort( unique_name )) && ext <= 99 )
  589.                                         sprintf( unique_name, "%s.%ld", ad->ad_HostName, ++ext );
  590.                                 Permit();
  591.                                 /*
  592.                                 **      Name unique?
  593.                                 **/
  594.                                 if ( ! mp ) {
  595.                                         /*
  596.                                         **      Copy the name.
  597.                                         **/
  598.                                         if ( ad->ad_HostName = DupStr( ad, unique_name )) {
  599.                                                 /*
  600.                                                 **      Uppercase it.
  601.                                                 **/
  602.                                                 tmp = ad->ad_HostName;
  603.                                                 while ( *tmp ) {
  604.                                                         *tmp = toupper( *tmp );
  605.                                                         tmp++;
  606.                                                 }
  607.                                                 /*
  608.                                                 **      Create the port.
  609.                                                 **/
  610.                                                 if ( ad->ad_Port = CreateMsgPort()) {
  611.                                                         /*
  612.                                                         **      Initialize and add the port.
  613.                                                         **/
  614.                                                         ad->ad_Port->mp_Node.ln_Name = ad->ad_HostName;
  615.                                                         ad->ad_Port->mp_Node.ln_Pri  = 0;
  616.                                                         AddPort( ad->ad_Port );
  617.                                                 } else if ( ecode )
  618.                                                         *ecode = RXERR_OUT_OF_MEMORY;
  619.                                         } else if ( ecode )
  620.                                                 *ecode = RXERR_OUT_OF_MEMORY;
  621.                                 } else if ( ecode )
  622.                                         *ecode = RXERR_PORT_ALREADY_EXISTS;
  623.                         } else if ( ecode )
  624.                                 *ecode = RXERR_NO_PORT_NAME;
  625.                 } else if ( ecode )
  626.                         *ecode = RXERR_NO_PORT_NAME;
  627.  
  628.                 /*
  629.                 **      Do we have a port now?
  630.                 **/
  631.                 if ( ad->ad_Port ) {
  632.                         /*
  633.                         **      Find the commandlist.
  634.                         **/
  635.                         if ( tag = FindTagItem( AC_CommandList, attr )) {
  636.                                 if ( ad->ad_Commands = ( REXXCOMMAND * )tag->ti_Data ) {
  637.                                         /*
  638.                                         **      Setup the AmigaDOS parser.
  639.                                         **/
  640.                                         if ( ad->ad_DOSParser = ( struct RDArgs * )AllocDosObject( DOS_RDARGS, NULL )) {
  641.                                                 ad->ad_DOSParser->RDA_Flags = RDAF_NOPROMPT;
  642.                                                 /*
  643.                                                 **      Obtain file extention.
  644.                                                 **/
  645.                                                 if ( tag = FindTagItem( AC_FileExtention, attr ))
  646.                                                         ad->ad_FileExt = ( UBYTE * )tag->ti_Data;
  647.                                                 else
  648.                                                         ad->ad_FileExt = "rexx";
  649.                                                 return( rc );
  650.                                         } else if ( ecode )
  651.                                                 *ecode = RXERR_OUT_OF_MEMORY;
  652.                                 } else if ( ecode )
  653.                                         *ecode = RXERR_NO_COMMAND_LIST;
  654.                         } else if ( ecode )
  655.                                 *ecode = RXERR_NO_COMMAND_LIST;
  656.                 }
  657. #ifdef POOLS
  658.                 } else if ( ecode )
  659.                         *ecode = RXERR_OUT_OF_MEMORY;
  660. #endif
  661.                 /*
  662.                 **      Bliep error...bliep....
  663.                 **/
  664.                 CoerceMethod( cl, ( Object * )rc, OM_DISPOSE );
  665.         }
  666.         return( 0L );
  667. }
  668.  
  669. /*
  670. **      OM_DISPOSE.
  671. **/
  672. STATIC ULONG ARexxDispose( Class *cl, Object *obj, Msg msg )
  673. {
  674.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  675.         struct RexxMsg          *rxm;
  676.  
  677.         /*
  678.         **      Do we have a port?
  679.         **/
  680.         if ( ad->ad_Port ) {
  681.                 /*
  682.                 **      Remove the port from the public list
  683.                 **/
  684.                 RemPort( ad->ad_Port );
  685.                 /*
  686.                 **      Wait for and handle all
  687.                 **      messages still pending.
  688.                 **/
  689.                 if ( ad->ad_PendCnt ) {
  690.                         while ( ad->ad_PendCnt ) {
  691.                                 /*
  692.                                 **      Wait for a message.
  693.                                 **/
  694.                                 WaitPort( ad->ad_Port );
  695.                                 /*
  696.                                 **      Get messages.
  697.                                 **/
  698.                                 while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port )) {
  699.                                         /*
  700.                                         **      Replyed message?
  701.                                         **/
  702.                                         if ( rxm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  703.                                                 /*
  704.                                                 **      Free the message and decrease the
  705.                                                 **      pending counter.
  706.                                                 **/
  707.                                                 FreeRexxCommand( rxm );
  708.                                                 ad->ad_PendCnt--;
  709.                                         } else
  710.                                                 /*
  711.                                                 **      Tell'm where getting out of here.
  712.                                                 **/
  713.                                                 ReplyRexxCommand( rxm, -20, ( LONG )"Host object closing down", NULL );
  714.                                 }
  715.                         }
  716.                 } else {
  717.                         /*
  718.                         **      In case there are no messages pending we
  719.                         **      still need to reply all that is waiting at
  720.                         **      the port.
  721.                         **/
  722.                         while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port ))
  723.                                 ReplyRexxCommand( rxm, -20, ( LONG )"Host object closing down", NULL );
  724.                 }
  725.  
  726.                 /*
  727.                 **      Delete the port.
  728.                 **/
  729.                 DeleteMsgPort( ad->ad_Port );
  730.         }
  731.  
  732.         /*
  733.         **      Delete the AmigaDOS parser.
  734.         **/
  735.         if ( ad->ad_DOSParser )
  736.                 FreeDosObject( DOS_RDARGS, ad->ad_DOSParser );
  737.  
  738.         /*
  739.         **      Delete the port name.
  740.         **/
  741.         if ( ad->ad_HostName )
  742.                 FreeMemory( ad->ad_HostName );
  743.  
  744. #ifdef POOLS
  745.         /*
  746.         **      Free the pool.
  747.         **/
  748.         LibDeletePool( ad->ad_MemPool );
  749. #endif
  750.  
  751.         /*
  752.         **      Let the superclass do the rest.
  753.         **/
  754.         return( DoSuperMethodA( cl, obj, msg ));
  755. }
  756.  
  757. /*
  758. **      ACM_EXECUTE.
  759. **/
  760. STATIC ULONG ARexxExecute( Class *cl, Object *obj, struct acmExecute *acme )
  761. {
  762.         AD                              *ad = ( AD * )INST_DATA( cl, obj );
  763.         REXXCOMMAND                     *rco;
  764.         REXXARGS                        *ra;
  765.         struct RexxMsg                  *rxm;
  766.         UBYTE                           *args, *tmp, *result = NULL, *com;
  767.         UWORD                            numargs = 0, len = 0;
  768.         ULONG                            r = 20, r2;
  769.  
  770.         /*
  771.         **      Allocate a private copy of the command string.
  772.         **/
  773.         if ( com = ( UBYTE * )AllocMemory( strlen( acme->acme_CommandString ) + 2 )) {
  774.                 /*
  775.                 **      Make a copy terminated with a newline.
  776.                 **/
  777.                 strcpy( com, acme->acme_CommandString );
  778.                 strcat( com, "\n" );
  779.                 /*
  780.                 **      Find the length of the command
  781.                 **      and the start of the arguments.
  782.                 **/
  783.                 args = com;
  784.                 while ( isspace( *args ))   args++;
  785.                 tmp = args;
  786.                 while ( ! isspace( *args )) { len++; args++; }
  787.                 /*
  788.                 **      Look up the command.
  789.                 **/
  790.                 if ( rco = FindRXCommand( ad, tmp, len )) {
  791.                         /*
  792.                         **      Allocate a REXXARGS structure.
  793.                         **/
  794.                         if ( ra = ( REXXARGS * )AllocMemory( sizeof( REXXARGS ))) {
  795.                                 /*
  796.                                 **      Args expected?
  797.                                 **/
  798.                                 if ( rco->rc_ArgTemplate ) {
  799.                                         /*
  800.                                         **      Count the expected number of arguments.
  801.                                         **/
  802.                                         tmp = rco->rc_ArgTemplate;
  803.                                         while ( *tmp != '\n' ) {
  804.                                                 if ( *tmp++ != ',' ) numargs++;
  805.                                         }
  806.                                         numargs++;
  807.                                         /*
  808.                                         **      Allocate space to parse the args.
  809.                                         **/
  810.                                         if ( ra->ra_ArgList = ( ULONG * )AllocMemory( numargs * sizeof( ULONG ))) {
  811.                                                 /*
  812.                                                 **      Setup the parser.
  813.                                                 **/
  814.                                                 ad->ad_DOSParser->RDA_Source.CS_Buffer = args;
  815.                                                 ad->ad_DOSParser->RDA_Source.CS_Length = strlen( args );
  816.                                                 ad->ad_DOSParser->RDA_Source.CS_CurChr = 0;
  817.                                                 ad->ad_DOSParser->RDA_DAList           = NULL;
  818.                                                 ad->ad_DOSParser->RDA_Buffer           = NULL;
  819.                                                 /*
  820.                                                 **      Parse the args.
  821.                                                 **/
  822.                                                 if ( ReadArgs( rco->rc_ArgTemplate, ra->ra_ArgList, ad->ad_DOSParser )) {
  823.                                                         /*
  824.                                                         **      Run command.
  825.                                                         **/
  826.                                                         ( rco->rc_Func )( ra, NULL );
  827.                                                         /*
  828.                                                         **      Store results.
  829.                                                         **/
  830.                                                         r      = ra->ra_RC;
  831.                                                         r2     = ra->ra_RC2;
  832.                                                         result = ra->ra_Result;
  833.                                                         FreeArgs( ad->ad_DOSParser );
  834.                                                 } else {
  835.                                                         r  = 10;
  836.                                                         r2 = IoErr();
  837.                                                 }
  838.                                                 /*
  839.                                                 **      Deallocate arg list.
  840.                                                 **/
  841.                                                 FreeMemory( ra->ra_ArgList );
  842.                                         } else
  843.                                                 r2 = ERROR_NO_FREE_STORE;
  844.                                 } else {
  845.                                         /*
  846.                                         **      Run command.
  847.                                         **/
  848.                                         ( rco->rc_Func )( ra, NULL );
  849.                                         /*
  850.                                         **      Store results.
  851.                                         **/
  852.                                         r      = ra->ra_RC;
  853.                                         r2     = ra->ra_RC2;
  854.                                         result = ra->ra_Result;
  855.                                 }
  856.                                 /*
  857.                                 **      Deallocate the REXXARGS structure.
  858.                                 **/
  859.                                 FreeMemory( ra );
  860.                         } else
  861.                                 r2 = ERROR_NO_FREE_STORE;
  862.                         /*
  863.                         **      When not passed to the rexx server
  864.                         **      we must close the given IO handle
  865.                         **      ourselves.
  866.                         **/
  867.                         if ( acme->acme_IO ) Close( acme->acme_IO );
  868.                 } else {
  869.                         /*
  870.                         **      We do not send the new-line to
  871.                         **      the ARexx server.
  872.                         **/
  873.                         com[ strlen( com ) - 1 ] = '\0';
  874.                         /*
  875.                         **      Unknown commands are shipped
  876.                         **      off to the REXX server.
  877.                         **/
  878.                         if ( rxm = CreateRexxCommand( ad, com, acme->acme_IO )) {
  879.                                 if ( ! CommandToRexx( ad, rxm ))
  880.                                         r2 = ERROR_NOT_IMPLEMENTED;
  881.                                 else
  882.                                         r = r2 = 0L;
  883.                         } else
  884.                                 r2 = ERROR_NO_FREE_STORE;
  885.                 }
  886.                 /*
  887.                 **      Deallocate the command copy.
  888.                 **/
  889.                 FreeMemory( com );
  890.         } else
  891.                 r2 = ERROR_NO_FREE_STORE;
  892.  
  893.         /*
  894.         **      Put the results into their
  895.         **      storage spaces.
  896.         **/
  897.         if ( acme->acme_RC     ) *( acme->acme_RC     ) = r;
  898.         if ( acme->acme_RC2    ) *( acme->acme_RC2    ) = r2;
  899.         if ( acme->acme_Result ) *( acme->acme_Result ) = result;
  900.  
  901.         return( 1L );
  902. }
  903.  
  904. /*
  905. **      OM_GET.
  906. **/
  907. STATIC ULONG ARexxGet( Class *cl, Object *obj, struct opGet *opg )
  908. {
  909.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  910.         ULONG                   rc = 1L;
  911.  
  912.         /*
  913.         **      What do they want?
  914.         **/
  915.         switch ( opg->opg_AttrID ) {
  916.  
  917.                 case    AC_HostName:
  918.                         *( opg->opg_Storage ) = ( ULONG )ad->ad_HostName;
  919.                         break;
  920.  
  921.                 case    AC_RexxPortMask:
  922.                         *( opg->opg_Storage ) = ( 1L << ad->ad_Port->mp_SigBit );
  923.                         break;
  924.  
  925.                 default:
  926.                         rc = DoSuperMethodA( cl, obj, ( Msg )opg );
  927.                         break;
  928.         }
  929.         return( rc );
  930. }
  931.  
  932. /*
  933. **      ACM_HANDLE_EVENT.
  934. **/
  935. STATIC ULONG ARexxHandleEvent( Class *cl, Object *obj, Msg msg )
  936. {
  937.         struct RexxMsg          *rxm, *org;
  938.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  939.         ULONG                    rc = 1L;
  940.  
  941.         /*
  942.         **      Get the messages from the port.
  943.         **/
  944.         while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port )) {
  945.                 /*
  946.                 **      A Rexx command?
  947.                 **/
  948.                 if (( rxm->rm_Action & RXCODEMASK ) != RXCOMM )
  949.                         ReplyMsg(( struct Message * )rxm );
  950.                 else if ( rxm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  951.                         /*
  952.                         **      Reply'd message. See if it was started
  953.                         **      as a script.
  954.                         **/
  955.                         if ( org = ( struct RexxMsg * )rxm->rm_Args[ 15 ] ) {
  956.                                 if ( rxm->rm_Result1 )
  957.                                         ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  958.                                 else
  959.                                         ReplyRexxCommand( org, 0, 0, ( UBYTE * )rxm->rm_Result2 );
  960.                         }
  961.                         /*
  962.                         **      Free the message and decrease the
  963.                         **      pending counter.
  964.                         **/
  965.                         FreeRexxCommand( rxm );
  966.                         ad->ad_PendCnt--;
  967.                 } else if ( ARG0( rxm ))
  968.                         /*
  969.                         **      Execute message.
  970.                         **/
  971.                         DoRXCommand( ad, rxm );
  972.                 else
  973.                         ReplyMsg(( struct Message * )rxm );
  974.         }
  975. }
  976.  
  977. /*
  978. **      Class dispatcher.
  979. **/
  980. STATIC SAVEDS ASM ULONG ARexxDispatch( REG(A0) Class *cl, REG(A2) Object *obj, REG(A1) Msg msg )
  981. {
  982.         ULONG                   rc = 0L;
  983.  
  984.         /*
  985.         **      Evaluate the method.
  986.         **/
  987.         switch ( msg->MethodID ) {
  988.  
  989.                 case    OM_NEW:
  990.                         rc = ARexxNew( cl, obj, ( struct opSet * )msg );
  991.                         break;
  992.  
  993.                 case    OM_GET:
  994.                         rc = ARexxGet( cl, obj, ( struct opGet * )msg );
  995.                         break;
  996.  
  997.                 case    OM_DISPOSE:
  998.                         rc = ARexxDispose( cl, obj, msg );
  999.                         break;
  1000.  
  1001.                 case    ACM_HANDLE_EVENT:
  1002.                         rc = ARexxHandleEvent( cl, obj, msg );
  1003.                         break;
  1004.  
  1005.                 case    ACM_EXECUTE:
  1006.                         rc = ARexxExecute( cl, obj, ( struct acmExecute * )msg );
  1007.                         break;
  1008.  
  1009.                 default:
  1010.                         rc = DoSuperMethodA( cl, obj, msg );
  1011.                         break;
  1012.         }
  1013.         return ( rc );
  1014. }
  1015.